package org.ysling.litemall.wx.web;
// Copyright (c) [ysling] [927069313@qq.com]
// [litemall-plus] is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//             http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import lombok.extern.slf4j.Slf4j;
import org.ysling.litemall.core.service.NotifyCoreService;
import org.ysling.litemall.core.tasks.impl.OrderCommentTask;
import org.ysling.litemall.core.tasks.service.TaskService;
import org.ysling.litemall.core.utils.response.ResponseUtil;
import org.ysling.litemall.core.validator.Order;
import org.ysling.litemall.core.validator.Sort;
import org.ysling.litemall.core.weixin.service.WeixinPayCoreService;
import org.ysling.litemall.db.domain.*;
import org.ysling.litemall.db.service.*;
import org.ysling.litemall.db.constant.AftersaleConstant;
import org.ysling.litemall.db.constant.OrderConstant;
import org.ysling.litemall.db.constant.OrderHandleOption;
import org.ysling.litemall.wx.annotation.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 售后服务
 *
 * 目前只支持订单整体售后，不支持订单商品单个售后
 *
 * 一个订单只能有一个售后记录
 */
@Slf4j
@RestController
@RequestMapping("/wx/aftersale")
@Validated
public class WxAftersaleController {

    @Autowired
    private LitemallAftersaleService aftersaleService;
    @Autowired
    private LitemallOrderService orderService;
    @Autowired
    private LitemallOrderGoodsService orderGoodsService;
    @Autowired
    private LitemallGoodsProductService goodsProductService;
    @Autowired
    private WeixinPayCoreService payCoreService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private NotifyCoreService notifyCoreService;
    @Autowired
    private LitemallBrandService brandService;

    /**
     * 售后列表
     *
     * @param userId   用户ID
     * @param status   状态类型，如果是空则是全部
     * @param page     分页页数
     * @param limit    分页大小
     * @param sort     排序字段
     * @param order    排序方式
     * @return 售后列表
     */
    @GetMapping("list")
    public Object list(@LoginUser Integer userId,
                       @RequestParam Short status,
                       @RequestParam(defaultValue = "1") Integer page,
                       @RequestParam(defaultValue = "10") Integer limit,
                       @Sort @RequestParam(defaultValue = "add_time") String sort,
                       @Order @RequestParam(defaultValue = "desc") String order) {
        if (Objects.isNull(userId)) {
            return ResponseUtil.unlogin();
        }

        List<LitemallAftersale> aftersaleList = aftersaleService.queryList(userId, status, page, limit, sort, order);

        List<Map<String, Object>> aftersaleVoList = new ArrayList<>(aftersaleList.size());
        for (LitemallAftersale aftersale : aftersaleList) {
            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(aftersale.getOrderId());

            Map<String, Object> aftersaleVo = new HashMap<>();
            aftersaleVo.put("aftersale", aftersale);
            aftersaleVo.put("statusText", AftersaleConstant.statusText(aftersale));
            aftersaleVo.put("goodsList", orderGoodsList);
            aftersaleVoList.add(aftersaleVo);
        }

        return ResponseUtil.okList(aftersaleVoList, aftersaleList);
    }

    /**
     * 售后详情
     *
     * @param orderId 订单ID
     * @return 售后详情
     */
    @GetMapping("detail")
    public Object detail(@LoginUser Integer userId, @NotNull Integer orderId) {
        if (Objects.isNull(userId)) {
            return ResponseUtil.unlogin();
        }

        // 订单信息
        LitemallOrder order = orderService.findById(userId, orderId);
        if (order == null) {
            LitemallBrand brand = brandService.findByUserId(userId);
            if (brand == null){
                return ResponseUtil.fail("订单不存在");
            }
            order = orderService.findByBrandId(brand.getId() , orderId);
            if (order == null){
                return ResponseUtil.fail( "订单不存在");
            }
        }

        List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
        if (orderGoodsList == null || orderGoodsList.size() <= 0){
            return ResponseUtil.fail( "订单不存在");
        }

        LitemallAftersale aftersale = aftersaleService.findByOrderId(order.getUserId(), orderId);
        if (aftersale == null){
            return ResponseUtil.fail( "无售后记录");
        }

        Map<String, Object> data = new HashMap<String, Object>();
        data.put("aftersale", aftersale);
        data.put("order", order);
        data.put("orderGoods", orderGoodsList);
        return ResponseUtil.ok(data);
    }

    /**
     * 申请售后
     *
     * @param userId   用户ID
     * @param aftersale 用户售后信息
     * @return 操作结果
     */
    @PostMapping("submit")
    public Object submit(@LoginUser Integer userId, @RequestBody LitemallAftersale aftersale) {
        if (Objects.isNull(userId)) {
            return ResponseUtil.unlogin();
        }
        Object error = validate(aftersale);
        if (error != null) {
            return error;
        }
        // 进一步验证
        Integer orderId = aftersale.getOrderId();
        if(Objects.isNull(orderId)){
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(userId, orderId);
        if(Objects.isNull(order)){
            return ResponseUtil.badArgumentValue();
        }

        // 订单必须完成才能进入售后流程。
        OrderHandleOption handleOption = OrderConstant.build(order);
        if(!handleOption.isAftersale()){
            return ResponseUtil.fail( "不能申请售后");
        }

        BigDecimal amount = order.getActualPrice().subtract(order.getFreightPrice());
        if(aftersale.getAmount().compareTo(amount) > 0){
            return ResponseUtil.fail( "退款金额不正确");
        }

        Short afterStatus = order.getAftersaleStatus();
        if(afterStatus.equals(AftersaleConstant.STATUS_RECEPT) || afterStatus.equals(AftersaleConstant.STATUS_REFUND)){
            return ResponseUtil.fail( "已申请售后");
        }

        // 如果有旧的售后记录则删除（例如用户已取消，管理员拒绝）
        aftersaleService.deleteByOrderId(userId, orderId);
        aftersale.setStatus(AftersaleConstant.STATUS_REQUEST);
        aftersale.setAftersaleSn(aftersaleService.generateAftersaleSn(userId));
        aftersale.setUserId(userId);
        aftersaleService.add(aftersale);

        //修改订单状态
        order.setOrderStatus(OrderConstant.STATUS_PUT_AFTERSALE);
        // 订单的aftersale_status和售后记录的status是一致的。
        order.setAftersaleStatus(AftersaleConstant.STATUS_REQUEST);
        if (orderService.updateVersionSelective(order) == 0){
            throw new RuntimeException("更新数据已失效");
        }

        //删除评论超时定时任务
        taskService.removeTask(new OrderCommentTask(orderId));

        //给商家发送通知
        notifyCoreService.aftersaleRefundNotify(order , aftersale);
        return ResponseUtil.ok();
    }

    /**
     * 取消售后
     *
     * 如果管理员还没有审核，用户可以取消自己的售后申请
     *
     * @param userId   用户ID
     * @param aftersale 用户售后信息
     * @return 操作结果
     */
    @PostMapping("cancel")
    public Object cancel(@LoginUser Integer userId, @RequestBody LitemallAftersale aftersale) {
        if (Objects.isNull(userId)) {
            return ResponseUtil.unlogin();
        }
        Integer id = aftersale.getId();
        if(id == null){
            return ResponseUtil.badArgument();
        }
        LitemallAftersale aftersaleOne = aftersaleService.findById(userId, id);
        if(aftersaleOne == null){
            return ResponseUtil.badArgument();
        }

        Integer orderId = aftersaleOne.getOrderId();
        LitemallOrder order = orderService.findById(userId, orderId);
        if(!order.getUserId().equals(userId)){
            return ResponseUtil.badArgumentValue();
        }

        // 订单必须完成才能进入售后流程。
        if(!OrderConstant.isPutAftersaleStatus(order)){
            return ResponseUtil.fail( "不能取消售后");
        }

        Short afterStatus = order.getAftersaleStatus();
        if(!afterStatus.equals(AftersaleConstant.STATUS_REQUEST)){
            return ResponseUtil.fail( "不能取消售后");
        }

        aftersale.setUserId(userId);
        aftersale.setStatus(AftersaleConstant.STATUS_CANCEL);
        if (aftersaleService.updateVersionSelective(aftersale) == 0){
            throw new RuntimeException("系统繁忙");
        }

        // 订单的aftersale_status和售后记录的status是一致的。
        orderService.updateAftersaleStatus(orderId, AftersaleConstant.STATUS_CANCEL);
        return ResponseUtil.ok();
    }

    /**
     * 审核通过
     * @param aftersale
     * @return
     */
    @PostMapping("/recept")
    public Object recept(@RequestBody LitemallAftersale aftersale) {
        LitemallOrder order = orderService.findById(aftersale.getOrderId());
        if (order == null) {
            return ResponseUtil.badArgument();
        }

        LitemallAftersale aftersaleOne = aftersaleService.findByOrderId(order.getUserId(),order.getId());
        if(aftersaleOne == null){
            return ResponseUtil.fail("售后不存在");
        }

        if(!aftersaleOne.getStatus().equals(AftersaleConstant.STATUS_REQUEST)){
            return ResponseUtil.fail("售后不能进行审核通过操作");
        }

        aftersaleOne.setStatus(AftersaleConstant.STATUS_RECEPT);
        aftersaleOne.setHandleTime(LocalDateTime.now());
        if (aftersaleService.updateVersionSelective(aftersaleOne) == 0) {
            return ResponseUtil.fail("售后修改失败");
        }

        //订单也要更新售后状态
        order.setAftersaleStatus(AftersaleConstant.STATUS_RECEPT);
        order.setOrderStatus(OrderConstant.STATUS_DISPOSE_AFTERSALE);
        if (orderService.updateVersionSelective(order) == 0) {
            throw new RuntimeException("更新数据已失效");
        }

        return ResponseUtil.ok();
    }


    /**
     * 审核驳回
     * @param aftersale
     * @return
     */
    @PostMapping("/reject")
    public Object reject(@RequestBody LitemallAftersale aftersale) {
        LitemallOrder order = orderService.findById(aftersale.getOrderId());
        if (order == null) {
            return ResponseUtil.badArgument();
        }

        LitemallAftersale aftersaleOne = aftersaleService.findByOrderId(order.getUserId(),order.getId());
        if(aftersaleOne == null){
            return ResponseUtil.fail("售后不存在");
        }

        if(!aftersaleOne.getStatus().equals(AftersaleConstant.STATUS_REQUEST)){
            return ResponseUtil.fail("售后不能进行审核拒绝操作");
        }

        aftersaleOne.setStatus(AftersaleConstant.STATUS_REJECT);
        aftersaleOne.setHandleTime(LocalDateTime.now());
        if (aftersaleService.updateVersionSelective(aftersaleOne) == 0) {
            return ResponseUtil.fail("售后更新失败");
        }

        //订单也要更新售后状态
        order.setAftersaleStatus(AftersaleConstant.STATUS_REJECT);
        order.setOrderStatus(OrderConstant.STATUS_REJECT_AFTERSALE);
        if (orderService.updateVersionSelective(order) == 0){
            throw new RuntimeException("更新数据失效");
        }
        return ResponseUtil.ok();
    }

    /**
     * 售后退款
     * @param aftersale
     * @return
     */
    @PostMapping("/refund")
    public Object refund(@RequestBody LitemallAftersale aftersale) {
        LitemallOrder order = orderService.findById(aftersale.getOrderId());
        if (order == null) {
            return ResponseUtil.badArgument();
        }

        LitemallAftersale aftersaleOne = aftersaleService.findByOrderId(order.getUserId(),order.getId());
        if(aftersaleOne == null){
            return ResponseUtil.fail("售后不存在");
        }

        if(!aftersaleOne.getStatus().equals(AftersaleConstant.STATUS_RECEPT)){
            return ResponseUtil.fail("售后不能进行退款操作");
        }

        // 微信退款
        WxPayRefundResult refundResult = payCoreService.wxPayAftersaleRefund(order , aftersaleOne);

        //修改售后信息
        aftersaleOne.setHandleTime(LocalDateTime.now());
        aftersaleOne.setStatus(AftersaleConstant.STATUS_REFUND);
        if (aftersaleService.updateVersionSelective(aftersaleOne) == 0) {
            return ResponseUtil.fail( "售后更新失败");
        }

        // 记录订单退款相关信息
        order.setRefundType("微信退款接口");
        order.setRefundTime(LocalDateTime.now());
        order.setRefundAmount(order.getActualPrice());
        order.setRefundContent(refundResult.getRefundId());
        order.setAftersaleStatus(AftersaleConstant.STATUS_REFUND);
        //修改订单状态
        order.setOrderStatus(OrderConstant.STATUS_FINISH_AFTERSALE);
        if (orderService.updateVersionSelective(order) == 0) {
            throw new RuntimeException("更新数据已失效");
        }

        // NOTE
        // 如果是“退货退款”类型的售后，这里退款说明用户的货已经退回，则需要商品货品数量增加
        // 开发者也可以删除一下代码，在其他地方增加商品货品入库操作
        if(Objects.equals(aftersale.getType() ,AftersaleConstant.TYPE_GOODS_REQUIRED)) {
            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
            for (LitemallOrderGoods orderGoods : orderGoodsList) {
                Integer productId = orderGoods.getProductId();
                Short number = orderGoods.getNumber();
                if(goodsProductService.addStock(productId, number) == 0){
                    throw new RuntimeException("库存增加失败");
                }
            }
        }
        return ResponseUtil.ok();
    }

    private Object validate(LitemallAftersale aftersale) {
        if (aftersale == null) {
            return ResponseUtil.badArgument();
        }
        Short type = aftersale.getType();
        if (type == null) {
            return ResponseUtil.badArgument();
        }
        BigDecimal amount = aftersale.getAmount();
        if (amount == null) {
            return ResponseUtil.badArgument();
        }
        String reason = aftersale.getReason();
        if (Objects.isNull(reason)) {
            return ResponseUtil.badArgument();
        }
        return null;
    }
}